home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / TURB_VIS / TCYBER25 / CYTERM.ZIP / CYTERM.PAS < prev    next >
Pascal/Delphi Source File  |  1994-10-20  |  37KB  |  1,507 lines

  1. {
  2. Turbo Vision CyberTools 2.5
  3. (C) 1994 Steve Goldsmith
  4. All Rights Reserved
  5.  
  6. CyberTerm is a powerful multi-session ANSI terminal application using Async
  7. Professional 2.01 from Turbo Power.  CyberScript compiler included with
  8. complete IDE support built into app.
  9.  
  10. Borland Pascal 7.x or Turbo Pascal 7.x, Turbo Vision 2.x and Async
  11. Professional 2.x from Turbo Power are required to compile.
  12.  
  13. Set IDE directories to
  14.  
  15. \BP\UNITS;
  16. \BP\EXAMPLES\DOS\TVDEMO;
  17. \BP\EXAMPLES\DOS\TVFM;
  18. \BP\APRO;
  19.  
  20. I used \BP\APRO when I installed Async Pro 2.01.  The rest of the path names
  21. use BP 7.x defaults.  If you changed any of these then use the correct paths
  22. in Options|Directories...  APDEFINE.INC in Async Pro was in its default state.
  23. See APP.INC for global compiler switches.
  24. }
  25.  
  26. {$I APP.INC}
  27. {$X+}
  28.  
  29. program CyberTerm;
  30.  
  31. uses
  32.  
  33.   Dos,                           {system units}
  34.   Memory, Drivers, Objects,      {tv units}
  35.   Views, Menus, Dialogs, Editors,
  36.   App, MsgBox, StdDlg, ColorSel,
  37.   Gadgets, HelpFile,             {tv demo units}
  38.   ViewText,                      {tvfm units}
  39.   ApMisc, OoAbsPcl,              {async pro units}
  40.   TermDlgs, CommDlgs, TVStr,     {cybertools units}
  41.   CTHelp, CTCmds;
  42.  
  43. type
  44.  
  45.   TCyberTerm = object(TApplication)
  46.     AppOptions : word;
  47.     PhoneData : TTermConfigDlgRec;
  48.     GenData : TTermGenDlgRec;
  49.     GenOpts : TTermGenOptsRec;
  50.     Clock : PClockView;
  51.     Heap : PHeapView;
  52.     ClipWindow : PCyEditWindow;
  53.     constructor Init;
  54.     function ErrorBox : boolean;
  55.     procedure AboutBox;
  56.     procedure Idle; virtual;
  57.     procedure ClearDeskTop;
  58.     procedure LogWindow;
  59.     function OpenEditor (FileName : FNameStr; Visible : Boolean) : PCyEditWindow;
  60.     procedure RestoreDesktop (F : PathStr);
  61.     procedure SaveDeskTop (F : PathStr);
  62.     procedure GetEvent (var Event : TEvent); virtual;
  63.     function GetPalette : PPalette; virtual;
  64.     procedure HandleEvent(var Event: TEvent); virtual;
  65.     procedure InitMenuBar; virtual;
  66.     procedure InitStatusLine; virtual;
  67.     procedure OutOfMemory; virtual;
  68.     procedure LoadDesktop (var S : TStream);
  69.     procedure StoreDesktop (var S : TStream);
  70.   end;
  71.  
  72. const
  73.  
  74.   appViewDocBuf = 8192;       {buffer size for viewing doc file}
  75.   appLogWinBuf  = 16384;      {buffer size for log window}
  76.   appHelpInUse  = $8000;      {used by help system}
  77.   appHelpName = 'CTHELP.HLP'; {help file name}
  78.   appDocName  = 'CYBER.DOC';  {doc file name}
  79.   appCfgName = 'CYTERM.CFG';  {config file name}
  80.   appExeName  = 'CYTERM.EXE'; {name used to locate .exe for older dos}
  81.   appCfgHeaderLen = 10;       {header used by config stream}
  82.   appCfgHeader : string[appCfgHeaderLen] = 'CYBERTERM'#26;
  83.  
  84.   CSysColor = #$00#$00#$00;   {app palette additions for tv system stuff}
  85.   CSysPal   = #136#137#138;
  86.  
  87. constructor TCyberTerm.Init;
  88.  
  89. var
  90.  
  91.   R : TRect;
  92.  
  93. begin
  94.   MaxHeapSize := 12288; {192K app heap}
  95.   LowMemSize := 2048;   {32K  safety pool}
  96.   inherited Init;
  97.   RegisterObjects;     {register stuff for stream access}
  98.   RegisterViews;
  99.   RegisterMenus;
  100.   RegisterDialogs;
  101.   RegisterApp;
  102.   RegisterHelpFile;
  103.   RegisterEditors;
  104.   RegisterTerm;         {register term objects}
  105.  
  106.   GetExtent (R);        {gadgets included with tvdemo}
  107.   R.A.Y := R.B.Y-1;
  108.   R.B.X := R.B.X-1;
  109.   R.A.X := R.B.X-8;
  110.   Heap := New (PHeapView,Init(R));
  111.   Heap^.GrowMode := gfGrowAll;
  112.   Insert (Heap);
  113.  
  114.   GetExtent (R);
  115.   R.B.Y := R.A.Y+1;
  116.   R.B.X := R.B.X-1;
  117.   R.A.X := R.B.X-8;
  118.   Clock := New (PClockView,Init (R));
  119.   Insert (Clock);
  120.  
  121.   RestoreDeskTop (appCfgName);
  122.   AboutBox;
  123.   LogWindow;
  124.  
  125.   EditorDialog := StdEditorDialog;
  126.   ClipWindow := OpenEditor ('', False); {create clip board}
  127.   if ClipWindow <> nil then
  128.   begin
  129.     Clipboard := ClipWindow^.Editor;
  130.     Clipboard^.CanUndo := false
  131.   end;
  132.   DisableCommands ([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  133.   cmUndo, cmFind, cmReplace, cmSearchAgain, cmCloseAll,cmAbortScript,
  134.   cmHangUp,cmEchoToggle,cmAbortXfer,cmCapture]);
  135. end;
  136.  
  137. {
  138. Display and return true if async error else return false.
  139. }
  140.  
  141. function TCyberTerm.ErrorBox : boolean;
  142.  
  143. begin
  144.   if GetAsyncStatus = ecOk then
  145.     ErrorBox := false
  146.   else
  147.   begin
  148.     MessageBox (#3+StatusStr (GetAsyncStatus),nil,mfOkButton+mfError);
  149.     ErrorBox := true
  150.   end
  151. end;
  152.  
  153. {
  154. Show program name, version, (C) and mode.
  155. }
  156.  
  157. procedure TCyberTerm.AboutBox;
  158.  
  159. begin
  160.   HelpCtx := hcAbout;
  161.   MessageBox(
  162.     #3'Turbo Vision CyberTools 2.5'#13+
  163.     #3'(C) 1994 Steve Goldsmith'#13+
  164. {$IFDEF DPMI}
  165.     #3'CyberTerm DPMI',
  166. {$ELSE}
  167.     #3'CyberTerm REAL',
  168. {$ENDIF}
  169.     nil, mfInformation or mfOKButton);
  170.   HelpCtx := hcNoContext
  171. end;
  172.  
  173. {
  174. Update commands, gadgets and terminal windows during idle processing.
  175. }
  176.  
  177. procedure TCyberTerm.Idle;
  178.  
  179. function IsTileable (P : PView) : boolean; far;
  180.  
  181. begin
  182.   IsTileable := (P^.Options and ofTileable <> 0) and
  183.   (P^.State and sfVisible <> 0)
  184. end;
  185.  
  186. begin
  187.   inherited Idle;
  188.   Clock^.Update;                               {update tvdemo gadgets}
  189.   Heap^.Update;
  190.   if Desktop^.Current <> nil then              {see if anything is}
  191.   begin                                        {on the desk top}
  192.     EnableCommands ([cmCloseAll]);
  193.     if Desktop^.FirstThat (@IsTileable) <> nil then {see if any tileable}
  194.       EnableCommands ([cmTile,cmCascade])           {windows are on the}
  195.     else                                            {desk top}
  196.       DisableCommands ([cmTile,cmCascade]);
  197.     Message (Desktop,evBroadcast,cmTermIdle,@Self)  {do all terms idle tasks}
  198.   end
  199.   else
  200.     DisableCommands ([cmCloseAll,cmTile,cmCascade]);
  201.   if ((Desktop^.Current <> nil) and
  202.   (Desktop^.Current^.State and sfModal = sfModal))
  203.   or (AppOptions and appHelpInUse = appHelpInUse) then {see if modal dialog}
  204.     DisableCommands ([cmQuit])                         {is on the desk top}
  205.   else
  206.     EnableCommands ([cmQuit]);
  207. end;
  208.  
  209. {
  210. Close all windows on desk top.
  211. }
  212.  
  213. procedure TCyberTerm.ClearDeskTop;
  214.  
  215. procedure CloseDlg (P : PView); far;
  216.  
  217. begin
  218.   Message (P,evCommand,cmClose,nil)
  219. end;
  220.  
  221. begin
  222.   Desktop^.ForEach (@CloseDlg)
  223. end;
  224.  
  225. {
  226. Log window logs comm events.
  227. }
  228.  
  229. procedure TCyberTerm.LogWindow;
  230.  
  231. var
  232.  
  233.   LogWin : PLogWin;
  234.  
  235. begin
  236.   LogWin := New (PLogWin, Init ('Log',appLogWinBuf));
  237.   LogWin^.HelpCtx := hcLogWindow;
  238.   InsertWindow (LogWin)
  239. end;
  240.  
  241. {
  242. Open text editor.
  243. }
  244.  
  245. function TCyberTerm.OpenEditor (FileName : FNameStr; Visible : Boolean) : PCyEditWindow;
  246.  
  247. var
  248.  
  249.   P : PWindow;
  250.   R : TRect;
  251.  
  252. begin
  253.   DeskTop^.GetExtent(R);
  254.   Dec (R.B.Y,7);
  255.   P := New (PCyEditWindow, Init (R, FileName, wnNoNumber));
  256.   P^.HelpCtx := hcTextEditor;
  257.   if not Visible then P^.Hide;
  258.   OpenEditor := PCyEditWindow (Application^.InsertWindow(P));
  259. end;
  260.  
  261. {
  262. Restore desk top stream.
  263. }
  264.  
  265. procedure TCyberTerm.RestoreDesktop (F : PathStr);
  266.  
  267. var
  268.  
  269.   S : PStream;
  270.   Signature : string[appCfgHeaderLen];
  271.  
  272. begin
  273.   S := New (PBufStream,Init (F,stOpenRead,1024));
  274.   if LowMemory then OutOfMemory
  275.   else
  276.     if S^.Status <> stOk then
  277.     begin
  278.       MessageBox (#3'Unable to open file',nil,mfOkButton+mfError)
  279.     end
  280.     else
  281.     begin
  282.       Signature[0] := Char (appCfgHeaderLen);
  283.       S^.Read (Signature[1],appCfgHeaderLen);
  284.       if Signature = appCfgHeader then {see if signature is right}
  285.       begin
  286.         S^.Read (GenData,SizeOf (GenData)); {read data from stream}
  287.         S^.Read (GenOpts,SizeOf (GenOpts));
  288.         LoadDesktop (S^);
  289.         LoadIndexes (S^);
  290.         if PhoneData.PhoneList.List <> nil then {dispose old list}
  291.           Dispose (PhoneData.PhoneList.List,Done);
  292.         PhoneData.PhoneList.List := PPhoneCollection (S^.Get);
  293.         ShadowAttr := GetColor (136);   {tv shadow color}
  294.         SysColorAttr := (GetColor (137) shl 8) or GetColor (137); {tv system error color}
  295.         ErrorAttr := GetColor (138);    {tv palette index error color}
  296.         Application^.ReDraw; {draw app with new config}
  297.         if S^.Status <> stOk then
  298.           MessageBox (#3'Stream error',nil,mfOkButton+mfError);
  299.       end
  300.       else
  301.         MessageBox (#3'Invalid configuration format',nil,mfOkButton+mfError)
  302.     end;
  303.   Dispose (S,Done)
  304. end;
  305.  
  306. {
  307. Save desk top stream.
  308. }
  309.  
  310. procedure TCyberTerm.SaveDesktop (F : PathStr);
  311.  
  312. var
  313.  
  314.   CfgFile : File;
  315.   S : PStream;
  316.  
  317. begin
  318.   S := New(PBufStream,Init (F,stCreate,1024));
  319.   if not LowMemory and (S^.Status = stOk) then
  320.   begin
  321.     S^.Write (appCfgHeader[1],appCfgHeaderLen);
  322.     S^.Write (GenData,SizeOf (GenData));
  323.     S^.Write (GenOpts,SizeOf (GenOpts));
  324.     StoreDesktop (S^);
  325.     StoreIndexes (S^);
  326.     S^.Put (PhoneData.PhoneList.List);
  327.     if S^.Status <> stOk then
  328.     begin {if stream error then delete file}
  329.       MessageBox (#3'Could not create stream',nil,mfOkButton+mfError);
  330.       Dispose (S,Done);
  331.       Assign (CfgFile,F);
  332.       {$I-} Erase (CfgFile); {$I+}
  333.       Exit
  334.     end
  335.   end;
  336.   Dispose (S,Done)
  337. end;
  338.  
  339. {
  340. Intercept cmHelp to display help even when views are in modal state.
  341. }
  342.  
  343. procedure TCyberTerm.GetEvent (var Event : TEvent);
  344.  
  345. function CalcHelpName : PathStr;
  346.  
  347. var
  348.  
  349.   EXEName : PathStr;
  350.   Dir : DirStr;
  351.   Name : NameStr;
  352.   Ext : ExtStr;
  353.  
  354. begin
  355.   if Lo (DosVersion) >= 3 then
  356.     EXEName := ParamStr (0)
  357.   else
  358.     EXEName := FSearch (appExeName, GetEnv ('PATH'));
  359.   FSplit (EXEName, Dir, Name, Ext);
  360.   if Dir[Length (Dir)] = '\' then
  361.     Dec (Dir[0]);
  362.   CalcHelpName := FSearch (appHelpName, Dir);
  363. end;
  364.  
  365. var
  366.  
  367.   W : PWindow;
  368.   HFile : PHelpFile;
  369.   HelpStrm : PDosStream;
  370.  
  371. begin
  372.   inherited GetEvent (Event);
  373.   case Event.What of
  374.     evCommand:
  375.       if (Event.Command = cmHelp) and (AppOptions and appHelpInUse = 0) then
  376.       begin {process help command if not in use}
  377.         AppOptions := AppOptions or appHelpInUse; {help's in use}
  378.         HelpStrm := New (PDosStream, Init (CalcHelpName, stOpenRead));
  379.         HFile := New (PHelpFile, Init (HelpStrm));
  380.         if HelpStrm^.Status <> stOk then
  381.         begin
  382.           MessageBox (#3'Could not open help file', nil, mfError + mfOkButton);
  383.           Dispose (HFile, Done);
  384.         end
  385.         else
  386.         begin
  387.           W := New (PHelpWindow,Init (HFile, GetHelpCtx));
  388.           if ValidView (W) <> nil then
  389.           begin
  390.             DisableCommands ([cmHelp]);
  391.             ExecView (W);
  392.             Dispose (W, Done);
  393.             EnableCommands ([cmHelp])
  394.           end;
  395.           ClearEvent (Event)
  396.         end;
  397.         AppOptions := AppOptions and not appHelpInUse
  398.       end;
  399.     evMouseDown:
  400.       if Event.Buttons <> 1 then
  401.         Event.What := evNothing
  402.   end
  403. end;
  404.  
  405. {
  406. Get custom app palette.
  407. }
  408.  
  409. function TCyberTerm.GetPalette: PPalette;
  410.  
  411. const
  412.  
  413.   CNewColor = CAppColor+CHelpColor+CSysColor;
  414.   CNewBlackWhite = CAppBlackWhite+CHelpBlackWhite+CSysColor;
  415.   CNewMonochrome = CAppMonochrome+CHelpMonochrome+CSysColor;
  416.   P: array[apColor..apMonochrome] of string[Length (CNewColor)] =
  417.   (CNewColor, CNewBlackWhite, CNewMonochrome);
  418.  
  419. begin {add additional entries to the normal application palettes}
  420.   GetPalette := @P[AppPalette];
  421. end;
  422.  
  423. {
  424. Handle app events.
  425. }
  426.  
  427. procedure TCyberTerm.HandleEvent(var Event: TEvent);
  428.  
  429. {
  430. Return focused file name from dir tree window.  If the extension param is not
  431. null then that extension is used.
  432. }
  433.  
  434. function TreeFileName (TW : PDirWindow; EStr : PathStr; ReadFlag : boolean) : PathStr;
  435.  
  436. var
  437.  
  438.   F : file;
  439.   FName : PathStr;
  440.  
  441. begin
  442.   FName := UpCaseStr (TW^.FocDirName+TW^.NameLine^.Data^);
  443.   if (EStr <> '') and (FName[byte (FName[0])] <> '\') then {force extension}
  444.     FName := AddExtStr (FName,EStr);
  445.   if ReadFlag then
  446.     TreeFileName := FName
  447.   else
  448.   begin
  449.     Assign (F,FName);
  450.     {$I-} Reset (F); {$I+}
  451.     if IoResult = 0 then {see if file exists before writes}
  452.     begin
  453.       {$I-} Close (F); {$I+}
  454.       if MessageBox (FName+' already exists.  Erase and continue?',
  455.       nil,mfConfirmation or mfYesNoCancel) = cmYes then
  456.         TreeFileName := FName
  457.       else
  458.         TreeFileName := ''
  459.     end
  460.     else
  461.       TreeFileName := FName {doesn't exist, so return name}
  462.   end
  463. end;
  464.  
  465. {
  466. View doc file.
  467. }
  468.  
  469. procedure ViewTextFile (FileName : PathStr);
  470.  
  471. var
  472.  
  473.   T : PTextWindow;
  474.   R : TRect;
  475.  
  476. begin
  477.   GetExtent (R);
  478.   R.Grow (-5,-4);
  479.   T := New(PTextWindow, Init(R, FileName));
  480.   T^.Options := T^.Options or ofCentered;
  481.   InsertWindow (T)
  482. end;
  483.  
  484. {
  485. Load .CGF file.
  486. }
  487.  
  488. procedure LoadConfigFile (TW : PDirWindow);
  489.  
  490. var
  491.  
  492.   F : PathStr;
  493.  
  494. begin
  495.   F := TreeFileName (TW,'CFG',true);
  496.   if F <> '' then
  497.     RestoreDeskTop (F)
  498. end;
  499.  
  500. {
  501. Save .CFG file.
  502. }
  503.  
  504. procedure SaveConfigFile (TW : PDirWindow);
  505.  
  506. var
  507.  
  508.   F : PathStr;
  509.  
  510. begin
  511.   F := TreeFileName (TW,'CFG',false);
  512.   if F <> '' then
  513.     SaveDeskTop (F)
  514. end;
  515.  
  516. {
  517. Return focused term window or nil if none focused.
  518. }
  519.  
  520. function GetFocusTerm : PTermWin;
  521.  
  522. var
  523.  
  524.   FT : PTermWin;
  525.  
  526. function IsFocused (V : PView) : boolean; far;
  527.  
  528. begin
  529.   IsFocused := (TypeOf (V^) = TypeOf (TTermWin)) and
  530.   (PTermWin (V)^.State and sfFocused <> 0)
  531. end;
  532.  
  533. begin
  534.   FT := PTermWin (Desktop^.FirstThat (@IsFocused));
  535.   if FT = nil then
  536.     MessageBox ('No terminal windows focused on desk top.',nil,mfOkButton+mfError);
  537.   GetFocusTerm := FT
  538. end;
  539.  
  540. {
  541. Return first term window in Z order or nil if none focused.
  542. }
  543.  
  544. function GetFirstTerm : PTermWin;
  545.  
  546. var
  547.  
  548.   FT : PTermWin;
  549.  
  550. function IsThere (V : PView) : boolean; far;
  551.  
  552. begin
  553.   IsThere := (TypeOf (V^) = TypeOf (TTermWin))
  554. end;
  555.  
  556. begin
  557.   FT := PTermWin (Desktop^.FirstThat (@IsThere));
  558.   if FT = nil then
  559.     MessageBox (#3'No terminal windows on desk top.',nil,mfOkButton+mfError);
  560.   GetFirstTerm := FT
  561. end;
  562.  
  563. {
  564. Return focused editor window or nil if none focused.
  565. }
  566.  
  567. function GetEditor (FocFlag : boolean) : PCyEditWindow;
  568.  
  569. var
  570.  
  571.   FE : PCyEditWindow;
  572.  
  573. function IsFocused (V : PView) : boolean; far;
  574.  
  575. begin
  576.   if FocFlag then
  577.     IsFocused := (TypeOf (V^) = TypeOf (TCyEditWindow)) and
  578.     (PCyEditWindow (V)^.State and sfFocused <> 0)
  579.   else
  580.     IsFocused := (TypeOf (V^) = TypeOf (TCyEditWindow))
  581. end;
  582.  
  583. begin
  584.   FE := PCyEditWindow (Desktop^.FirstThat (@IsFocused));
  585.   if FE = nil then
  586.     MessageBox ('No editor windows focused on desk top.',nil,mfOkButton+mfError);
  587.   GetEditor := FE
  588. end;
  589.  
  590. {
  591. Hang up focused term window.
  592. }
  593.  
  594. procedure Hangup;
  595.  
  596. var
  597.  
  598.   T : PTermWin;
  599.  
  600. begin
  601.   T := GetFocusTerm;
  602.   if T <> nil then
  603.   begin
  604.     if T^.Valid (cmClose) then {if ok to close then ok to hang up too}
  605.       T^.CmdState := (T^.CmdState and not ctCmdDialPause) or
  606.       ctCmdHangUp {hang up line}
  607.   end
  608. end;
  609.  
  610. {
  611. Toggle focused term window's echo
  612. }
  613.  
  614. procedure ToggleEcho;
  615.  
  616. var
  617.  
  618.   T : PTermWin;
  619.  
  620. begin
  621.   T := GetFocusTerm;
  622.   if T <> nil then
  623.   begin
  624.     if T^.Term^.TermOptions and ctLocalEcho = 0 then
  625.       T^.Term^.TermOptions := T^.Term^.TermOptions or ctLocalEcho
  626.     else
  627.       T^.Term^.TermOptions := T^.Term^.TermOptions and not ctLocalEcho
  628.   end
  629. end;
  630.  
  631. {
  632. Capture toggle if term window's command state = 0 (no commands).
  633. }
  634.  
  635. procedure CaptureToggle (TW : PDirWindow);
  636.  
  637. var
  638.  
  639.   F : PathStr;
  640.   T : PTermWin;
  641.  
  642. begin
  643.   T := GetFirstTerm;
  644.   if T <> nil then
  645.   begin
  646.     if T^.CmdState = 0 then
  647.     begin
  648.       F := TreeFileName (TW,'CAP',true);
  649.       if F <> '' then
  650.         T^.Capture (F,0)
  651.     end
  652.     else
  653.       MessageBox ('Cannot capture while commands in progress.',nil,mfOkButton+mfError)
  654.   end
  655. end;
  656.  
  657. {
  658. New file list.
  659. }
  660.  
  661. procedure NewFileList;
  662.  
  663. var
  664.  
  665.   D : PStrListDlg;
  666.  
  667. begin
  668.   D := New (PStrListDlg,Init ('File List'));
  669.   D^.HelpCtx := hcFileList;
  670.   InsertWindow (D)
  671. end;
  672.  
  673. {
  674. Return first file list in Z order.
  675. }
  676.  
  677. function GetStrListDlg : PStrListDlg;
  678.  
  679. function IsStrList (V : PView) : boolean; far;
  680.  
  681. begin
  682.   IsStrList :=  TypeOf (V^) = TypeOf (TStrListDlg)
  683. end;
  684.  
  685. begin
  686.   GetStrListDlg := PStrListDlg (Desktop^.FirstThat (@IsStrList))
  687. end;
  688.  
  689. {
  690. Find first file list in Z order and handle missing and empty lists by
  691. returning nil.
  692. }
  693.  
  694. function GetFileList : PStrListDlg;
  695.  
  696. var
  697.  
  698.   D : PStrListDlg;
  699.  
  700. begin
  701.   D := GetStrListDlg;
  702.   if D <> nil then
  703.   begin
  704.     if D^.StrBox^.List^.Count = 0 then
  705.     begin
  706.       MessageBox (#3'File list empty',nil,mfOkButton+mfError);
  707.       D^.Focus;
  708.       D := nil
  709.     end
  710.   end
  711.   else
  712.   begin
  713.     MessageBox ('No file list found on desk top.',nil,mfOkButton+mfError);
  714.     NewFileList;
  715.     D := nil
  716.   end;
  717.   GetFileList := D
  718. end;
  719.  
  720. {
  721. Download files.  Handle getting name for X modem and ASCII, since they are
  722. not provided by protocol.
  723. }
  724.  
  725. procedure Download (ProtNum : word);
  726.  
  727. var
  728.  
  729.   T : PTermWin;
  730.   D : PStrListDlg;
  731.  
  732. begin
  733.   T := GetFocusTerm;
  734.   if T <> nil then
  735.     if T^.CmdState = 0 then
  736.     begin
  737.       if ProtNum in[Xmodem..Xmodem1KG,Ascii] then
  738.       begin
  739.         D := GetFileList;
  740.         if D <> nil then
  741.         begin
  742.           T^.FileListColl := PStringCollection (D^.StrBox^.List);
  743.           T^.ProtocolNum := ProtNum;
  744.           T^.CmdState := ctCmdXferInit+ctCmdDownload
  745.         end
  746.       end
  747.       else
  748.       begin
  749.         T^.ProtocolNum := ProtNum;
  750.         T^.CmdState := ctCmdXferInit+ctCmdDownload
  751.       end
  752.     end
  753. end;
  754.  
  755. {
  756. Upload files from file list.
  757. }
  758.  
  759. procedure Upload (ProtNum : word);
  760.  
  761. var
  762.  
  763.   T : PTermWin;
  764.   D : PStrListDlg;
  765.  
  766. begin
  767.   T := GetFocusTerm;
  768.   if T <> nil then
  769.     if T^.CmdState = 0 then
  770.     begin
  771.       D := GetFileList;
  772.       if D <> nil then
  773.       begin
  774.         T^.FileListColl := PStringCollection (D^.StrBox^.List);
  775.         T^.ProtocolNum := ProtNum;
  776.         T^.CmdState := ctCmdXferInit
  777.       end
  778.     end
  779. end;
  780.  
  781. {
  782. Abort file transfer in progress.
  783. }
  784.  
  785. procedure AbortXfer;
  786.  
  787. var
  788.  
  789.   T : PTermWin;
  790.  
  791. begin
  792.   T := GetFocusTerm;
  793.   if T <> nil then
  794.     if T^.CmdState and ctCmdXfer <> 0 then
  795.       T^.CmdState := T^.CmdState or ctCmdXferAbort
  796. end;
  797.  
  798. {
  799. Abort script
  800. }
  801.  
  802. procedure AbortScript;
  803.  
  804. var
  805.  
  806.   T : PTermWin;
  807.  
  808. begin
  809.   T := GetFocusTerm;
  810.   if T <> nil then
  811.   begin
  812.     if T^.Valid (cmClose) then {if ok to close then ok to abort too}
  813.     begin
  814.       if T^.CmdState and ctCmdScript <> 0 then
  815.       begin
  816.         T^.CmdState := T^.CmdState and not
  817.         (ctCmdDial or ctCmdDialPause or ctCmdScript);
  818.         T^.UpdateLog ('Script aborted')
  819.       end
  820.       else
  821.         MessageBox ('Unable to abort script',nil,mfOkButton+mfError);
  822.     end
  823.   end
  824. end;
  825.  
  826. {
  827. Return terminal window pointer if no async or view buffer errors.
  828. }
  829.  
  830. function TermWindow (P : PTermRec) : PTermWin;
  831.  
  832. var
  833.  
  834.   TW : PTermWin;
  835.  
  836. {see if view is a term win and uses same com port}
  837.  
  838. function IsTermWin (V : PView) : boolean; far;
  839.  
  840. begin
  841.   IsTermWin :=  (TypeOf (V^) = TypeOf (TTermWin)) and
  842.   (PTermWin (V)^.UPort.GetComName = P^.ComName)
  843. end;
  844.  
  845. begin
  846.   pointer (TW) := Desktop^.FirstThat (@IsTermWin);
  847.   if TW <> nil then
  848.   begin
  849.     if TW^.Valid (cmClose) then {see if it's ok to close}
  850.     begin
  851.       TW^.Close;
  852.       TW := nil
  853.     end
  854.   end;
  855.   if TW = nil then              {see if ok to create new window}
  856.   begin
  857.     New (TW,Init (P^.Name,P,@GenOpts));
  858.     if ValidView (TW) <> nil then
  859.     begin
  860.       if ErrorBox then
  861.       begin
  862.         Dispose (TW,Done);
  863.         TW := nil
  864.       end
  865.       else
  866.         if TW^.Term^.DrawBuf^[TW^.Term^.Lines] = nil then
  867.         begin
  868.           TW^.UpdateLog ('View buffer too large'); {ran out of heap!}
  869.           Dispose (TW,Done);
  870.           TW := nil;
  871.           MessageBox ('View buffer too large.  Reduce terminal length and try again.',
  872.           nil,mfOkButton+mfError)
  873.         end
  874.         else
  875.           InsertWindow (TW)
  876.     end
  877.   end
  878.   else
  879.     TW := nil;
  880.   TermWindow := TW
  881. end;
  882.  
  883. {
  884. Open phone book to dial, add, edit and delete records.  Records added to list
  885. are preserved even if dialog exits with cmCancel.
  886. }
  887.  
  888. procedure PhoneBook;
  889.  
  890. var
  891.  
  892.   D : PTermConfigDlg;
  893.   TW : PTermWin;
  894.  
  895. begin
  896.   D := New (PTermConfigDlg,Init);
  897.   if PhoneData.PhoneList.List = nil then       {create new list if needed}
  898.     PhoneData.PhoneList.List := New (PPhoneCollection,Init (0,1));
  899.   D^.PhoneCollPtr := PhoneData.PhoneList.List; {tell dialog where list is}
  900.   D^.HelpCtx := hcPhoneBookDlg;
  901.   if ExecuteDialog (D,@PhoneData) = cmOK then
  902.   begin
  903.     if PhoneData.PhoneList.List^.Count > 0 then {check for empty list}
  904.     begin
  905.       TW := TermWindow (PhoneData.PhoneList.List^.At (
  906.       PhoneData.PhoneList.Selection));
  907.       if TW <> nil then {init modem and dial if window created}
  908.       begin
  909.         TW^.HelpCtx := hcTermWindow;
  910.         if TW^.Term^.TermOptions and ctReqCTS <> 0 then
  911.           TW^.CmdState := ctCmdInit+ctCmdDial+ctCmdCTSWait {wait for cts}
  912.         else
  913.           TW^.CmdState := ctCmdInit+ctCmdDial              {skip cts wait}
  914.       end
  915.     end
  916.   end
  917. end;
  918.  
  919. {
  920. Compile and run focused edit window script in term window.
  921. }
  922.  
  923. procedure RunScript;
  924.  
  925. var
  926.  
  927.   D : PTermConfigDlg;
  928.   TW : PTermWin;
  929.   E : PCyEditWindow;
  930.   C : TScriptCompile;
  931.  
  932. begin
  933.   E := GetEditor (true); {get focused editor}
  934.   if E <> nil then
  935.   begin
  936.     D := New (PTermConfigDlg,Init);
  937.     if PhoneData.PhoneList.List = nil then       {create new list if needed}
  938.       PhoneData.PhoneList.List := New (PPhoneCollection,Init (0,1));
  939.     D^.PhoneCollPtr := PhoneData.PhoneList.List; {tell dialog where list is}
  940.     D^.HelpCtx := hcPhoneBookDlg;
  941.     if ExecuteDialog (D,@PhoneData) = cmOK then
  942.     begin
  943.       if PhoneData.PhoneList.List^.Count > 0 then {check for empty list}
  944.       begin
  945.         TW := TermWindow (PhoneData.PhoneList.List^.At (
  946.         PhoneData.PhoneList.Selection));
  947.         if TW <> nil then    {compile script if term window created}
  948.         begin
  949.           TW^.HelpCtx := hcTermWindow;
  950.           TW^.ScriptEng := New (PScriptEng,Init (TW));
  951.           C.Init (E,TW);
  952.           if C.Compile then
  953.           begin
  954.             if TW^.Term^.TermOptions and ctReqCTS <> 0 then
  955.               TW^.CmdState := ctCmdCTSWait+ctCmdScript {wait for cts before start}
  956.             else
  957.               TW^.CmdState := ctCmdScript;             {start script}
  958.             TW^.UpdateLog ('Start script')
  959.           end;
  960.           C.Done
  961.         end
  962.       end
  963.     end
  964.   end
  965. end;
  966.  
  967. {
  968. Open new text editor.
  969. }
  970.  
  971. procedure FileNew;
  972.  
  973. begin
  974.   OpenEditor ('', True)
  975. end;
  976.  
  977. {
  978. Open .SCR script source file.
  979. }
  980.  
  981. procedure FileOpen (TW : PDirWindow);
  982.  
  983. var
  984.  
  985.   F : PathStr;
  986.  
  987. begin
  988.   F := TreeFileName (TW,'',true);
  989.   if F <> '' then
  990.     OpenEditor(F,true)
  991. end;
  992.  
  993. {
  994. Save as .SCR script source file.
  995. }
  996.  
  997. procedure SaveFileAs (TW : PDirWindow);
  998.  
  999. var
  1000.  
  1001.   F : PathStr;
  1002.   E : PCyEditWindow;
  1003.  
  1004. begin
  1005.   F := TreeFileName (TW,'',false);
  1006.   if F <> '' then
  1007.   begin
  1008.     E := GetEditor (false); {get first editor in z order}
  1009.     if E <> nil then
  1010.     begin
  1011.       E^.Editor^.FileName := F;
  1012.       Message (E^.Owner, evBroadcast, cmUpdateTitle, nil);
  1013.       E^.Editor^.SaveFile;
  1014.       if E^.Editor = @Clipboard then
  1015.         E^.Editor^.FileName := ''
  1016.     end
  1017.   end
  1018. end;
  1019.  
  1020. {
  1021. Make clip window visible.
  1022. }
  1023.  
  1024. procedure ShowClip;
  1025.  
  1026. begin
  1027.   ClipWindow^.Select;
  1028.   ClipWindow^.Show
  1029. end;
  1030.  
  1031. {
  1032. General options.
  1033. }
  1034.  
  1035. procedure General;
  1036.  
  1037. var
  1038.  
  1039.   D : PTermGenDlg;
  1040.  
  1041. begin
  1042.   D := New (PTermGenDlg,Init);
  1043.   D^.HelpCtx := hcTermOpts;
  1044.   if ExecuteDialog (D,@GenData) <> cmCancel then
  1045.     GenDlgToGenOpts (GenData,GenOpts)
  1046. end;
  1047.  
  1048. {
  1049. Tree window is a file browser.
  1050. }
  1051.  
  1052. procedure TreeWindow (T : string; FMask : PathStr; ACmd : word);
  1053.  
  1054. var
  1055.  
  1056.   W : PDirWindow;
  1057.   Drive : PathStr;
  1058.  
  1059. begin
  1060.   GetDir (0,Drive);
  1061.   W := New (PDirWindow,Init (T,Drive,FMask,ACmd));
  1062.   W^.HelpCtx := hcTreeWindow;
  1063.   InsertWindow (W)
  1064. end;
  1065.  
  1066. {
  1067. Add file to file list.
  1068. }
  1069.  
  1070. procedure AddFileToList (TW : PDirWindow);
  1071.  
  1072. var
  1073.  
  1074.   I : integer;
  1075.   F : PathStr;
  1076.   D : PStrListDlg;
  1077.  
  1078. function IsStrList (V : PView) : boolean; far;
  1079.  
  1080. begin
  1081.   IsStrList :=  TypeOf (V^) = TypeOf (TStrListDlg)
  1082. end;
  1083.  
  1084. begin
  1085.   F := TreeFileName (TW,'',true);
  1086.   if F <> '' then
  1087.   begin
  1088.     D := PStrListDlg (Desktop^.FirstThat (@IsStrList));
  1089.     if D <> nil then
  1090.       with D^.StrBox^ do
  1091.       begin
  1092.         if (not LowMemory) and
  1093.         (not PStringCollection (List)^.Search (@F,I)) then
  1094.         begin
  1095.           List^.Insert (NewStr(F));       {add file name to list}
  1096.           SetRange (List^.Count);         {set list's range}
  1097.           FocusItem (List^.IndexOf (@F)); {focus inserted item}
  1098.           DrawView                        {draw box}
  1099.         end
  1100.       end
  1101.   end
  1102. end;
  1103.  
  1104. {
  1105. Switch between 25 and 43/50 line mode.
  1106. }
  1107.  
  1108. procedure ToggleVideo;
  1109.  
  1110. var
  1111.  
  1112.   NewMode : word;
  1113.   R : TRect;
  1114.  
  1115. begin
  1116.   NewMode := ScreenMode xor smFont8x8;
  1117.   if NewMode and smFont8x8 <> 0 then
  1118.     ShadowSize.X := 1
  1119.   else
  1120.     ShadowSize.X := 2;
  1121.   SetScreenMode (NewMode);
  1122.   Desktop^.GetExtent (R)
  1123. end;
  1124.  
  1125. {
  1126. Set custom TV color palette.
  1127. }
  1128.  
  1129. procedure Colors;
  1130.  
  1131. {custom color items}
  1132. function DlgColorItems (Palette: Word; const Next: PColorItem) : PColorItem;
  1133.  
  1134. const
  1135.  
  1136.   COffset : array[dpBlueDialog..dpGrayDialog] of Byte = (64, 96, 32);
  1137.  
  1138. var
  1139.  
  1140.   Offset : Byte;
  1141.  
  1142. begin
  1143.   Offset := COffset[Palette];
  1144.   DlgColorItems :=
  1145.     ColorItem ('Frame passive',     Offset,
  1146.     ColorItem ('Frame active',      Offset + 1,
  1147.     ColorItem ('Frame icons',       Offset + 2,
  1148.     ColorItem ('Scroll bar page',   Offset + 3,
  1149.     ColorItem ('Scroll bar icons',  Offset + 4,
  1150.     ColorItem ('Static text',       Offset + 5,
  1151.  
  1152.     ColorItem ('Label normal',      Offset + 6,
  1153.     ColorItem ('Label selected',    Offset + 7,
  1154.     ColorItem ('Label shortcut',    Offset + 8,
  1155.  
  1156.     ColorItem ('Button normal',     Offset + 9,
  1157.     ColorItem ('Button default',    Offset + 10,
  1158.     ColorItem ('Button selected',   Offset + 11,
  1159.     ColorItem ('Button disabled',   Offset + 12,
  1160.     ColorItem ('Button shortcut',   Offset + 13,
  1161.     ColorItem ('Button shadow',     Offset + 14,
  1162.  
  1163.     ColorItem ('Cluster normal',    Offset + 15,
  1164.     ColorItem ('Cluster selected',  Offset + 16,
  1165.     ColorItem ('Cluster shortcut',  Offset + 17,
  1166.  
  1167.     ColorItem ('Input normal',      Offset + 18,
  1168.     ColorItem ('Input selected',    Offset + 19,
  1169.     ColorItem ('Input arrow',       Offset + 20,
  1170.  
  1171.     ColorItem ('History button',    Offset + 21,
  1172.     ColorItem ('History sides',     Offset + 22,
  1173.     ColorItem ('History bar page',  Offset + 23,
  1174.     ColorItem ('History bar icons', Offset + 24,
  1175.  
  1176.     ColorItem ('List normal',       Offset + 25,
  1177.     ColorItem ('List focused',      Offset + 26,
  1178.     ColorItem ('List selected',     Offset + 27,
  1179.     ColorItem ('List divider',      Offset + 28,
  1180.  
  1181.     ColorItem('Information pane',  Offset + 29,
  1182.     Next))))))))))))))))))))))))))))));
  1183. end;
  1184.  
  1185. function HelpColorItems(const Next: PColorItem): PColorItem;
  1186.  
  1187. begin
  1188.   HelpColorItems :=
  1189.     ColorItem ('Frame passive',     128,
  1190.     ColorItem ('Frame active',      129,
  1191.     ColorItem ('Frame icons',       130,
  1192.     ColorItem ('Scroll bar page',   131,
  1193.     ColorItem ('Scroll bar icons',  132,
  1194.     ColorItem ('Normal text',       133,
  1195.     ColorItem ('Key word',          134,
  1196.     ColorItem ('Select key word',   135,
  1197.     Next))))))))
  1198. end;
  1199.  
  1200. function SysColorItems (const Next: PColorItem) : PColorItem;
  1201.  
  1202. begin
  1203.   SysColorItems :=
  1204.     ColorItem ('Shadow',       136,
  1205.     ColorItem ('System error', 137,
  1206.     ColorItem ('Index error',  138,
  1207.     Next)))
  1208. end;
  1209.  
  1210. var
  1211.  
  1212.   D : PColorDialog;
  1213.  
  1214. begin
  1215.   D := New (PColorDialog,Init ('',
  1216.   ColorGroup ('Desktop',     DesktopColorItems(nil),
  1217.   ColorGroup ('Menus',       MenuColorItems(nil),
  1218.   ColorGroup ('Gray Windows',WindowColorItems(wpGrayWindow,nil),
  1219.   ColorGroup ('Blue Windows',WindowColorItems(wpBlueWindow,nil),
  1220.   ColorGroup ('Cyan Windows',WindowColorItems(wpCyanWindow,nil),
  1221.   ColorGroup ('Gray Dialogs',DlgColorItems(dpGrayDialog,nil),
  1222.   ColorGroup ('Blue Dialogs',DlgColorItems(dpBlueDialog,nil),
  1223.   ColorGroup ('Cyan Dialogs',DlgColorItems(dpCyanDialog,nil),
  1224.   ColorGroup ('Help',        HelpColorItems(nil),
  1225.   ColorGroup ('System',      SysColorItems(nil),
  1226.   nil))))))))))));
  1227.   D^.HelpCtx := hcColorDialog;
  1228.   if ExecuteDialog (D,Application^.GetPalette) <> cmCancel then
  1229.   begin
  1230.     DoneMemory; {dispose all group buffers}
  1231.     ReDraw;     {redraw application with new palette}
  1232.     ShadowAttr := GetColor (136);   {tv shadow color}
  1233.     SysColorAttr := (GetColor (137) shl 8) or GetColor (137); {tv system error color}
  1234.     ErrorAttr := GetColor (138);    {tv palette index error color}
  1235.   end
  1236. end;
  1237.  
  1238. {
  1239. Force all oftileable windows to top.
  1240. }
  1241.  
  1242. procedure TileableOnTop (P : PView); far;
  1243.  
  1244. begin
  1245.   if (P^.Options and ofTileable = ofTileable) then
  1246.     P^.MakeFirst
  1247. end;
  1248.  
  1249. {
  1250. See if anything is on desk top.
  1251. }
  1252.  
  1253. function IsThere (P : PView) : Boolean; far;
  1254.  
  1255. begin
  1256.   IsThere := (P^.State and sfActive = sfActive)
  1257. end;
  1258.  
  1259. begin
  1260.   if Event.What = evCommand then
  1261.     case Event.Command of {we want to see these events before inherited}
  1262.       cmSaveAs  :
  1263.       begin
  1264.         TreeWindow ('Save As','*.SCR',cmSaveAs);
  1265.         ClearEvent (Event)
  1266.       end;
  1267.       cmCascade : Desktop^.ForEach (@TileableOnTop);
  1268.       cmTile    : Desktop^.ForEach (@TileableOnTop);
  1269.       cmQuit    :
  1270.       begin
  1271.         ClearDeskTop;        {try to close all windows on desk top}
  1272.         if DeskTop^.FirstThat (@IsThere) <> nil then
  1273.           ClearEvent (Event) {if any views on desk top then do not quit}
  1274.       end
  1275.     end;
  1276.   inherited HandleEvent (Event);
  1277.   case Event.What of
  1278.     evCommand:
  1279.     case Event.Command of             {process commands}
  1280.       cmPhoneBook     : PhoneBook;
  1281.       cmGeneral       : General;
  1282.       cmNewLogWin     : LogWindow;
  1283.       cmHangUp        : HangUp;
  1284.       cmEchoToggle    : ToggleEcho;
  1285.       cmToggleVideo   : ToggleVideo;
  1286.       cmRunScript     : RunScript;
  1287.       cmAbortScript   : AbortScript;
  1288.       cmColors        : Colors;
  1289.       cmSaveConfig    : TreeWindow ('Save Config Stream','*.CFG',cmSaveConfig);
  1290.       cmLoadConfig    : TreeWindow ('Load Config Stream','*.CFG',cmLoadConfig);
  1291.       cmFileBrowse    : TreeWindow ('File List Builder','*.*',cmAddFile);
  1292.       cmCapture       : TreeWindow ('Capture File','*.CAP',cmCapture);
  1293.       cmOpen          : TreeWindow ('Open Script Source','*.SCR',cmOpen);
  1294.       cmNewFileList   : NewFileList;
  1295.       cmNew           : FileNew;
  1296.       cmShowClip      : ShowClip;
  1297.       cmXmodemDown    : Download (Xmodem);
  1298.       cmXmodem1KDown  : Download (Xmodem1K);
  1299.       cmXmodem1KGDown : Download (Xmodem1KG);
  1300.       cmYmodemDown    : Download (Ymodem);
  1301.       cmYmodemGDown   : Download (YmodemG);
  1302.       cmZmodemDown    : Download (Zmodem);
  1303.       cmKermitDown    : Download (Kermit);
  1304.       cmAsciiDown     : Download (Ascii);
  1305.       cmXmodemUp      : Upload (Xmodem);
  1306.       cmXmodem1KUp    : Upload (Xmodem1K);
  1307.       cmXmodem1KGUp   : Upload (Xmodem1KG);
  1308.       cmYmodemUp      : Upload (Ymodem);
  1309.       cmYmodemGUp     : Upload (YmodemG);
  1310.       cmZmodemUp      : Upload (Zmodem);
  1311.       cmKermitUp      : Upload (Kermit);
  1312.       cmAsciiUp       : Upload (Ascii);
  1313.       cmAbortXfer     : AbortXfer;
  1314.       cmViewDoc       : ViewTextFile (appDocName);
  1315.       cmAbout         : AboutBox;
  1316.       cmCloseAll      : ClearDeskTop
  1317.     end;
  1318.     evBroadcast:
  1319.     case Event.Command of             {process broadcasts}
  1320.       cmSaveConfig    : SaveConfigFile (PDirWindow (Event.InfoPtr));
  1321.       cmLoadConfig    : LoadConfigFile (PDirWindow (Event.InfoPtr));
  1322.       cmAddFile       : AddFileToList (PDirWindow (Event.InfoPtr));
  1323.       cmCapture       : CaptureToggle (PDirWindow (Event.InfoPtr));
  1324.       cmOpen          : FileOpen (PDirWindow (Event.InfoPtr));
  1325.       cmSaveAs        : SaveFileAs (PDirWindow (Event.InfoPtr))
  1326.     end
  1327.   end
  1328. end;
  1329.  
  1330. {
  1331. Menu.
  1332. }
  1333.  
  1334. procedure TCyberTerm.InitMenuBar;
  1335.  
  1336. var
  1337.  
  1338.   R : TRect;
  1339.  
  1340. begin
  1341.   GetExtent (R);
  1342.   R.B.Y := R.A.Y+1;
  1343.   MenuBar := New (PMenuBar,Init (R,NewMenu (
  1344.     NewSubMenu ('~F~ile',hcFile,NewMenu (
  1345.       NewItem ('~R~un script','F9',kbF9,cmRunScript,hcRunScript,
  1346.       NewSubMenu ('~T~ext',hcText,NewMenu (
  1347.         NewItem ('~N~ew', 'F4', kbF4, cmNew, hcNewText,
  1348.         NewItem ('~O~pen...', 'F3', kbF3, cmOpen, hcOpenText,
  1349.         NewItem ('~S~ave', 'F2', kbF2, cmSave, hcSaveText,
  1350.         NewItem ('Sa~v~e as...', '', kbNoKey, cmSaveAs, hcSaveAsText,
  1351.         NewItem ('Save a~l~l', '', kbNoKey, cmSaveAll, hcSaveAllText,
  1352.         nil)))))),
  1353.         NewSubMenu ('~D~own load',hcDownload,NewMenu (
  1354.           NewItem ('~Z~ modem','',kbNoKey,cmZmodemDown,hcDownload,
  1355.           NewItem ('~Y~ modem','',kbNoKey,cmYmodemDown,hcDownload,
  1356.           NewItem ('Y modem ~G~','',kbNoKey,cmYmodemGDown,hcDownload,
  1357.           NewItem ('~X~ modem','',kbNoKey,cmXmodemDown,hcDownload,
  1358.           NewItem ('X modem ~1~K','',kbNoKey,cmXmodem1KDown,hcDownload,
  1359.           NewItem ('X mode~m~ 1KG','',kbNoKey,cmXmodem1KGDown,hcDownload,
  1360.           NewItem ('~K~ermit','',kbNoKey,cmKermitDown,hcDownload,
  1361.           NewItem ('~A~scii','',kbNoKey,cmAsciiDown,hcDownload,
  1362.           nil))))))))),
  1363.         NewSubMenu ('~U~p load',hcUpload,NewMenu (
  1364.           NewItem ('~Z~ modem','',kbNoKey,cmZmodemUp,hcUpload,
  1365.           NewItem ('~Y~ modem','',kbNoKey,cmYmodemUp,hcUpload,
  1366.           NewItem ('Y modem ~G~','',kbNoKey,cmYmodemGUp,hcUpload,
  1367.           NewItem ('~X~ modem','',kbNoKey,cmXmodemUp,hcUpload,
  1368.           NewItem ('X modem ~1~K','',kbNoKey,cmXmodem1KUp,hcUpload,
  1369.           NewItem ('X mode~m~ 1KG','',kbNoKey,cmXmodem1KGUp,hcUpload,
  1370.           NewItem ('~K~ermit','',kbNoKey,cmKermitUp,hcUpload,
  1371.           NewItem ('~A~scii','',kbNoKey,cmAsciiUp,hcUpload,
  1372.           nil))))))))),
  1373.       NewSubMenu ('~L~ist',hcList,NewMenu (
  1374.         NewItem ('~N~ew','',kbNoKey,cmNewFileList,hcNewFileList,
  1375.         NewItem ('~B~uilder...','',kbNoKey,cmFileBrowse,hcFileListBuild,
  1376.         nil))),
  1377.       NewSubMenu ('~C~onfig',hcConfig,NewMenu (
  1378.         NewItem ('~L~oad...','Ctrl+F3',kbCtrlF3,cmLoadConfig,hcLoadConfig,
  1379.         NewItem ('~S~ave...','Ctrl+F2',kbCtrlF2,cmSaveConfig,hcSaveConfig,
  1380.         nil))),
  1381.       NewLine (
  1382.       NewItem ('~V~iew doc','',kbNoKey,cmViewDoc,hcViewDoc,
  1383.       NewItem ('~A~bout','',kbNoKey,cmAbout,hcAbout,
  1384.       NewLine (
  1385.       NewItem ('E~x~it','Alt-X',kbAltX,cmQuit,hcExit,
  1386.       nil)))))))))))),
  1387.     NewSubMenu('~E~dit', hcEdit, NewMenu(
  1388.       StdEditMenuItems(
  1389.       NewLine(
  1390.       NewItem('~S~how clipboard', '', kbNoKey, cmShowClip, hcShowClip,
  1391.       nil)))),
  1392.     NewSubMenu('~S~earch', hcSearch, NewMenu(
  1393.       NewItem('~F~ind...', '', kbNoKey, cmFind, hcFind,
  1394.       NewItem('~R~eplace...', '', kbNoKey, cmReplace, hcReplace,
  1395.       NewItem('~S~earch again', '', kbNoKey, cmSearchAgain, hcSearchAgain,
  1396.       nil)))),
  1397.     NewSubMenu ('~T~erminal',hcTerminal,NewMenu (
  1398.       NewItem ('~P~hone book...','F7',kbF7,cmPhoneBook,hcPhoneBook,
  1399.       NewItem ('~C~apture...','',kbNoKey,cmCapture,hcCapture,
  1400.       NewItem ('~H~ang up','',kbNoKey,cmHangUp,hcHangUp,
  1401.       NewItem ('~E~cho toggle','',kbNoKey,cmEchoToggle,hcEchoToggle,
  1402.       NewItem ('~S~cript abort','',kbNoKey,cmAbortScript,hcAbortScript,
  1403.       NewItem ('Transfer ~a~bort','',kbNoKey,cmAbortXfer,hcAbortXfer,
  1404.       nil))))))),
  1405.     NewSubMenu ('~O~ptions',hcOptions,NewMenu (
  1406.       NewItem ('~T~erminal...','',kbNoKey,cmGeneral,hcOTerminal,
  1407.       NewItem ('~C~olors...','',kbNoKey,cmColors,hcOColors,
  1408.       NewItem ('~V~ideo toggle','',kbNoKey,cmToggleVideo,hcVideoToggle,
  1409.       nil)))),
  1410.     NewSubMenu ('~W~indow',hcWindows,NewMenu(
  1411.       StdWindowMenuItems (
  1412.       NewItem ('New ~l~og window','F8',kbF8,cmNewLogWin,hcNewLogWin,
  1413.       nil))),nil)))))))))
  1414. end;
  1415.  
  1416. {
  1417. Status line.
  1418. }
  1419.  
  1420. procedure TCyberTerm.InitStatusLine;
  1421.  
  1422. var
  1423.  
  1424.   R : TRect;
  1425.  
  1426. begin
  1427.   GetExtent (R);
  1428.   R.A.Y := R.B.Y-1;
  1429.   StatusLine := New (PStatusLine,Init(R,
  1430.     NewStatusDef (0,$FFFF,
  1431.       NewStatusKey ('~F1~ Help', kbF1, cmHelp,
  1432.       NewStatusKey ('',kbF2,cmSave,
  1433.       NewStatusKey ('',kbF3,cmOpen,
  1434.       NewStatusKey ('',kbF4,cmNew,
  1435.       NewStatusKey ('',kbF7,cmPhoneBook,
  1436.       NewStatusKey ('',kbF8,cmNewLogWin,
  1437.       NewStatusKey ('',kbF9,cmRunScript,
  1438.       NewStatusKey ('~Alt-F3~ Close',kbAltF3,cmClose,
  1439.       NewStatusKey ('~Alt-X~ Exit',kbAltX,cmQuit,
  1440.       NewStatusKey ('',kbCtrlF2,cmSaveConfig,
  1441.       NewStatusKey ('',kbCtrlF3,cmLoadConfig,
  1442.       NewStatusKey ('',kbCtrlF5,cmResize,
  1443.       NewStatusKey ('',kbF10,cmMenu,
  1444.       nil))))))))))))),nil)))
  1445. end;
  1446.  
  1447. {
  1448. Let user know if heap allocation cuts into the safety pool.
  1449. }
  1450.  
  1451. procedure TCyberTerm.OutOfMemory;
  1452.  
  1453. begin
  1454.   MessageBox ('Not enough memory available to complete operation.  Try closing some windows!',
  1455.   nil,mfError+mfOkButton);
  1456. end;
  1457.  
  1458. {
  1459. Load desk top from stream.
  1460. }
  1461.  
  1462. procedure TCyberTerm.LoadDesktop (var S : TStream);
  1463.  
  1464. var
  1465.  
  1466.   Pal : PString;
  1467.  
  1468. begin
  1469.   Pal := S.ReadStr;
  1470.   if Pal <> nil then
  1471.   begin
  1472.     Application^.GetPalette^ := Pal^;
  1473.     DoneMemory;
  1474.     DisposeStr (Pal)
  1475.   end
  1476. end;
  1477.  
  1478. {
  1479. Store desk top on stream.
  1480. }
  1481.  
  1482. procedure TCyberTerm.StoreDesktop(var S: TStream);
  1483.  
  1484. var
  1485.  
  1486.   Pal: PString;
  1487.  
  1488. begin
  1489.   Pal := @Application^.GetPalette^;
  1490.   S.WriteStr (Pal)
  1491. end;
  1492.  
  1493. {
  1494. Main app.
  1495. }
  1496.  
  1497. var
  1498.  
  1499.   CTApp : TCyberTerm;
  1500.  
  1501. begin
  1502.   CTApp.Init;
  1503.   SysErrorFunc := AppSystemError;
  1504.   CTApp.Run;
  1505.   CTApp.Done
  1506. end.
  1507.